import fs from 'fs';
import path from 'path';
import { format } from 'date-fns';

// 日志级别枚举
export enum LogLevel {
  DEBUG = 0,
  INFO = 1,
  WARN = 2,
  ERROR = 3,
  FATAL = 4
}

// 日志级别名称映射
const LOG_LEVEL_NAMES = {
  [LogLevel.DEBUG]: 'DEBUG',
  [LogLevel.INFO]: 'INFO',
  [LogLevel.WARN]: 'WARN',
  [LogLevel.ERROR]: 'ERROR',
  [LogLevel.FATAL]: 'FATAL'
};

// 日志配置接口
interface LoggerConfig {
  level: LogLevel;
  logToFile: boolean;
  logToConsole: boolean;
  logFilePath: string;
  maxFileSize: number; // MB
  maxFiles: number;
  timestampFormat: string;
}

// 默认配置
const defaultConfig: LoggerConfig = {
  level: LogLevel.INFO,
  logToFile: true,
  logToConsole: true,
  logFilePath: process.env.LOG_FILE_PATH || './logs',
  maxFileSize: 10, // 10MB
  maxFiles: 5,
  timestampFormat: 'yyyy-MM-dd HH:mm:ss'
};

// 日志记录器类
class Logger {
  private config: LoggerConfig;
  private currentLogFile: string;
  private logStream: fs.WriteStream | null = null;

  constructor(config: Partial<LoggerConfig> = {}) {
    this.config = { ...defaultConfig, ...config };
    this.currentLogFile = this.getLogFileName();
    this.ensureLogDirectory();
    this.rotateLogsIfNeeded();
  }

  // 确保日志目录存在
  private ensureLogDirectory(): void {
    if (!fs.existsSync(this.config.logFilePath)) {
      fs.mkdirSync(this.config.logFilePath, { recursive: true });
    }
  }

  // 获取日志文件名
  private getLogFileName(): string {
    const date = format(new Date(), 'yyyy-MM-dd');
    return path.join(this.config.logFilePath, `app-${date}.log`);
  }

  // 检查是否需要轮转日志
  private rotateLogsIfNeeded(): void {
    if (!this.config.logToFile) return;

    const newLogFile = this.getLogFileName();
    if (newLogFile !== this.currentLogFile) {
      this.closeLogStream();
      this.currentLogFile = newLogFile;
      this.rotateLogFiles();
    }
  }

  // 轮转日志文件
  private rotateLogFiles(): void {
    const logDir = this.config.logFilePath;
    const files = fs.readdirSync(logDir)
      .filter(file => file.startsWith('app-') && file.endsWith('.log'))
      .sort()
      .reverse();

    // 删除超出数量限制的旧日志文件
    while (files.length >= this.config.maxFiles) {
      const oldFile = files.pop();
      if (oldFile) {
        fs.unlinkSync(path.join(logDir, oldFile));
      }
    }

    // 检查当前日志文件大小
    if (fs.existsSync(this.currentLogFile)) {
      const stats = fs.statSync(this.currentLogFile);
      const fileSizeInMB = stats.size / (1024 * 1024);
      
      if (fileSizeInMB > this.config.maxFileSize) {
        const timestamp = format(new Date(), 'HH-mm-ss');
        const newFileName = this.currentLogFile.replace('.log', `-${timestamp}.log`);
        fs.renameSync(this.currentLogFile, newFileName);
      }
    }
  }

  // 关闭日志流
  private closeLogStream(): void {
    if (this.logStream) {
      this.logStream.end();
      this.logStream = null;
    }
  }

  // 获取日志流
  private getLogStream(): fs.WriteStream {
    if (!this.logStream) {
      this.logStream = fs.createWriteStream(this.currentLogFile, { flags: 'a' });
    }
    return this.logStream;
  }

  // 格式化日志消息
  private formatMessage(level: LogLevel, message: string, meta?: any): string {
    const timestamp = format(new Date(), this.config.timestampFormat);
    const levelName = LOG_LEVEL_NAMES[level];
    const metaStr = meta ? ` | ${JSON.stringify(meta)}` : '';
    
    return `[${timestamp}] [${levelName}] ${message}${metaStr}\n`;
  }

  // 写入日志
  private writeLog(level: LogLevel, message: string, meta?: any): void {
    if (level < this.config.level) return;

    const formattedMessage = this.formatMessage(level, message, meta);

    // 写入控制台
    if (this.config.logToConsole) {
      const consoleMethod = level >= LogLevel.ERROR ? 'error' : 
                           level >= LogLevel.WARN ? 'warn' : 
                           level >= LogLevel.INFO ? 'info' : 'log';
      console[consoleMethod](formattedMessage.trim());
    }

    // 写入文件
    if (this.config.logToFile) {
      try {
        this.rotateLogsIfNeeded();
        const stream = this.getLogStream();
        stream.write(formattedMessage);
      } catch (error) {
        console.error('Failed to write to log file:', error);
      }
    }
  }

  // 记录调试日志
  debug(message: string, meta?: any): void {
    this.writeLog(LogLevel.DEBUG, message, meta);
  }

  // 记录信息日志
  info(message: string, meta?: any): void {
    this.writeLog(LogLevel.INFO, message, meta);
  }

  // 记录警告日志
  warn(message: string, meta?: any): void {
    this.writeLog(LogLevel.WARN, message, meta);
  }

  // 记录错误日志
  error(message: string, meta?: any): void {
    this.writeLog(LogLevel.ERROR, message, meta);
  }

  // 记录致命错误日志
  fatal(message: string, meta?: any): void {
    this.writeLog(LogLevel.FATAL, message, meta);
  }

  // 记录HTTP请求日志
  http(method: string, url: string, statusCode: number, responseTime: number, userAgent?: string): void {
    const message = `${method} ${url} ${statusCode} ${responseTime}ms`;
    const meta = { method, url, statusCode, responseTime, userAgent };
    this.info(message, meta);
  }

  // 记录数据库操作日志
  db(operation: string, table: string, duration: number, success: boolean, error?: any): void {
    const message = `DB ${operation} on ${table} ${duration}ms ${success ? 'SUCCESS' : 'FAILED'}`;
    const meta = { operation, table, duration, success, error };
    
    if (success) {
      this.debug(message, meta);
    } else {
      this.error(message, meta);
    }
  }

  // 记录API调用日志
  api(apiName: string, method: string, duration: number, success: boolean, error?: any): void {
    const message = `API ${apiName} ${method} ${duration}ms ${success ? 'SUCCESS' : 'FAILED'}`;
    const meta = { apiName, method, duration, success, error };
    
    if (success) {
      this.info(message, meta);
    } else {
      this.error(message, meta);
    }
  }

  // 记录用户操作日志
  userAction(userId: string, action: string, details?: any): void {
    const message = `USER_ACTION ${userId} ${action}`;
    const meta = { userId, action, details };
    this.info(message, meta);
  }

  // 记录系统事件日志
  systemEvent(event: string, details?: any): void {
    const message = `SYSTEM_EVENT ${event}`;
    const meta = { event, details };
    this.info(message, meta);
  }

  // 清理资源
  close(): void {
    this.closeLogStream();
  }
}

// 创建默认日志记录器实例
export const logger = new Logger({
  level: (process.env.LOG_LEVEL as  unknown as LogLevel) || LogLevel.INFO,
  logToFile: true,
  logToConsole: true
});

// 导出日志记录器类
export default Logger;

// 进程退出时清理资源
process.on('exit', () => {
  logger.close();
});

process.on('SIGINT', () => {
  logger.close();
  process.exit(0);
});

process.on('SIGTERM', () => {
  logger.close();
  process.exit(0);
});
